

POINTER_ACTIVE_GAP = 1 
EFFECTIVE_RANGE = 15 
#DISPLAY_WIDTH = 2048
#DISPLAY_HEIGHT = 768 
DISPLAY_WIDTH = 5400 
DISPLAY_HEIGHT =  1920 
#DISPLAY_WIDTH = 24588 
#DISPLAY_HEIGHT =  3072
#DISPLAY_WIDTH = 1920
#DISPLAY_HEIGHT = 1080 

NOT_DEFINED = -1 

HEATMAP = 1
BUSYGRAPH = 2 
TESTGRAPH = 3 
DISTANCEGRAPH = 4 
VECTORGRAPH = 5 
TRENDGRAPH = 6 
WINDOWGRAPH = 7 
SPACEGRAPH = 8

# section direction - sanghwa
HORIZONTAL = 0
VERTICAL = 1


LOG_WINDOW_CHANGE = 1
LOG_WINDOW_NEW = 2
LOG_WINDOW_REMOVE = 3
LOG_WINDOW_MAXIMIZE = 4
LOG_WINDOW_MINIMIZE = 5
LOG_WINDOW_RESTORE = 6
LOG_WINDOW_Z_CHANGE = 7

LOG_SECTION_NEW = 8
LOG_SECTION_RESIZE = 9
LOG_SECTION_REMOVE = 10
LOG_SECTION_TILE = 11
LOG_SECTION_MINIMIZE_ALL = 12

LOG_POINTER_NEW = 13
LOG_POINTER_REMOVE = 14
LOG_POINTER_MOVE = 15
LOG_POINTER_CLICK = 16
LOG_POINTER_RELEASE = 17
LOG_POINTER_DCLICK = 18
LOG_POINTER_WHEEL = 19

LOG_POINTER_VECTOR = 20 
LOG_POINTER_ACTIVE = 21 

LOG_WINDOW_LIFETIME = 22 
LOG_WINDOW_SIZE = 23 

LOG_POINTER_MERGED = 24 
LOG_POINTER_COLOR = 25
LOG_WINDOW_DIS_SIZE = 26
LOG_WINDOW_DIS_TIME = 27

LOG_POINTER_RCLICK = 28
LOG_POINTER_TWO_SWIPE = 29
LOG_POINTER_THREE_SWIPE = 30
LOG_POINTER_MAGNIFY = 31

LOG_WINDOW_MOVE_TO =  32

LOG_SECTION_DYNAMIC = 33
LOG_SECTION_SHRINK = 34
LOG_SECTION_CLEAR = 35
LOG_SECTION_APPLY = 36
LOG_SECTION_FREE = 37
LOG_SECTION_TILE_DISPLAY = 38
LOG_SECTION_NORMAL = 39
LOG_SECTION = 40 
LOG_SECTION_DATAIN = 41
LOG_SECTION_NODATAIN = 42

LOG_WINDOW_SWAP = 43 
LOG_WINDOW_MAXIMIZE_SCREEN = 44

#ksy
LOG_POINTER_HIGHLIGHTT = 45
LOG_POINTER_HIGHLIGHTF = 46
LOG_POINTER_PCLICK = 47

class Log:
	def __init__(self, start, duration, participants, title, date, display):
		self.start_time = start
		self.duration = duration 
		self.users = participants
		self.name = title
		self.date = date 
		self.display_width = display[0] 
		self.display_height = display[1] 
		#print "display size", self.display_width, self.display_height

		self.section_list = []
		self.pointer_list = []
		self.window_list = []

	def registerSection(self, logdata, start):
		name = logdata[8] 
		current_section = None
		for section in self.section_list: 
			if section.name == name:
				current_section = section
				break
		if current_section == None:
			current_section = SectionLogObj(name) 
			self.section_list.append(current_section)
		current_section.addSection(logdata, start)


	def registerPointer(self, logdata, start):
		name = logdata[5] 
		type = logdata[4]
		if type == "NEW" or type == "REMOVE" :
			name = logdata[6] 
                name = name.upper()

		current_pointer = None
		for pointer in self.pointer_list: 
			if pointer.name == name:
				current_pointer = pointer
				break
		if current_pointer == None:
			current_pointer = PointerLogObj(name) 
			self.pointer_list.append(current_pointer)
		current_pointer.addPointer(logdata, start)

	def sortingPointer(self):
		for pointer in self.pointer_list: 
			name = pointer.name
			name_token = name.split(':')
                        if len(name_token) > 1 :
				if name_token[1] == '' :  
					name = 'untitled'
				else :
					name = name_token[1]
					name = name.upper()
                        else :
				name = name.upper()
			#i = ord(sort_name[0])
			pointer.name = name

		temp_list = self.pointer_list
		#print temp_list
		self.pointer_list = []
		max = len(temp_list)
		for ith in range(max): 
			name = temp_list[ith].name
			i = ord(name[0])
			jth  =0
			for pointer in self.pointer_list :
				name = pointer.name
				j = ord(name[0])
				if i < j  :
					self.pointer_list.insert(jth, temp_list[ith])	
					jth = -1
					break;
				jth += 1
			if jth != -1 : 
				self.pointer_list.append(temp_list[ith])
		del temp_list
		temp_list = []

	def registerWindow(self, logdata, start):
		type = logdata[4]
		name = ""
		if type == "MAXIMIZE" or type == "MINIMIZE" or type == "REMOVE" or type=="RESTORE": 
			name = logdata[5] 
		elif type == "Z": 
			return
		else :
			name = logdata[6] 

		current_window = None
		for window in self.window_list: 
			if window.name == name:
				current_window = window 
				break
		if current_window == None:
			current_window = WindowLogObj(name) 
			self.window_list.append(current_window)
		current_window.addWindow(logdata, start)


	def analyze(self, active_time): 
		total_strokes = 0
		total_action = 0
		for pointer in self.pointer_list:
			action = pointer.analyze(active_time)
			total_strokes +=  pointer.getNoOfStrokes()
			total_action += action 
		#print "total number of strokes = ", str(total_strokes)
		#print self.pointer_list[0].name, "total number of window action = ", str(total_action)

		total_action = 0
		for window in self.window_list:
			average, max, min, action = window.analyze()
			window.ave_size = average / (1.0 * self.display_width * self.display_height)
			window.max_size = max / (1.0 * self.display_width * self.display_height)
			window.min_size = min / (1.0 * self.display_width * self.display_height)
			#print "window ave_size=", window.ave_size, "max=", max, "min=", min
			total_action += action 
		print self.pointer_list[0].name, "total number of window action = ", str(total_action)

		'''
		total_applys = 0
		for section in self.section_list:
			tmp = section.analyze()
			total_applys += tmp 
		print self.pointer_list[0].name, "total number of apply = ", str(total_applys)
		'''



	def _destroy(self): 
		for section in self.section_list: 
			section._destroy()
			del section 
		del self.section_list
		for pointer in self.pointer_list: 
			pointer._destroy()
			del pointer
		del self.pointer_list
		for window in self.window_list: 
			window._destroy()
			del window 
		del self.window_list
		
# ------------------------------------------------------------
# LOG Object
# ------------------------------------------------------------
class LogObj:
	def __init__(self, name): 
		self.log_list = []
		self.name = name

	def _destroy(self): 
		for log in self.log_list: 
			del log
		del self.log_list

# ------------------------------------------------------------
# Pointer LOG
# ------------------------------------------------------------
class PointerLogObj(LogObj):
	def __init__(self, name): 
		LogObj.__init__(self, name)

		# (start_time, end_time)... 
		self.active_range= []
		self.no_clicks = 0
		self.no_dclicks = 0
		self.no_drags =0

	def addPointer(self, logdata, start):
		log = PointerLog(logdata, start)
		self.log_list.append(log)

	def _destroy(self): 
		self._clear()
		LogObj._destroy(self)

	def _clear(self): 
		for active_time in self.active_range: 
			del active_time
		del self.active_range
		self.active_range= []

	def getPosition(self, start, end): 
		l = []
		prev_x = -1
		prev_y = -1
		idx = 0
		max = len(self.log_list)
		for log in self.log_list :
			if log.mode == LOG_POINTER_MOVE :
				if log.time >= start :
					if log.time == start or prev_x == -1:
						prev_x = log.x
						prev_y = log.y
					break
				prev_x = log.x
				prev_y = log.y
			idx += 1 

		if idx != max : 
			temp  = (start, prev_x, prev_y)
			l.append(temp)

			for i in range(idx, max):
				log = self.log_list[i]
				if log.mode == LOG_POINTER_MOVE :
					if log.time <= end :
						temp  = (log.time, log.x, log.y)
						l.append(temp)
					else :
						temp  = (end, prev_x, prev_y)
						l.append(temp)
						break
					prev_x = log.x
					prev_y = log.y

		return l

	def getNoOfStrokes(self): 
		return len(self.log_list)

	def analyze(self, active_gap):
		self._clear()
		count = 0
		start_time = 0
		prev_time = 0
		prev_x = -1
		prev_y = -1

		#print self.name, ": number of strokes =", str(len(self.log_list))

		log_len = len(self.log_list)
		log_count =0
		no_of_action = 0
		# active =1, inactive= 0
		for log in self.log_list :
			log_count += 1
			if log.mode == LOG_POINTER_NEW :
				prev_time = log.time
				start_time = log.time
				count = 0 
			elif log.mode == LOG_POINTER_REMOVE :
				diff = log.time - prev_time
				if diff > active_gap:
					if count == 0 :
						active_slot = (0, start_time, log.time)
						self.active_range.append(active_slot)
					else :
						active_slot = (1, start_time, prev_time)
						self.active_range.append(active_slot)

						active_slot = (0, prev_time, log.time)
						self.active_range.append(active_slot)
				else :
					active_slot = (1, start_time, log.time)
					self.active_range.append(active_slot)

			elif log.mode == LOG_POINTER_MOVE :

				diff = log.time - prev_time
				if diff > active_gap:
					if count == 0: 
						active_slot = (0, start_time, log.time)
						self.active_range.append(active_slot)
					else :
						active_slot = (1, start_time, prev_time)
						self.active_range.append(active_slot)

						active_slot = (0, prev_time, log.time)
						self.active_range.append(active_slot)

					start_time = log.time
					count = 0
				else:
					count += 1
					if log_len == log_count :
						active_slot = (1, start_time, log.time)
						self.active_range.append(active_slot)
				prev_time = log.time 

			elif log.mode == LOG_POINTER_TWO_SWIPE or log.mode == LOG_POINTER_THREE_SWIPE or  log.mode ==LOG_POINTER_MAGNIFY :
				no_of_action +=1 
		return no_of_action 

class PointerLog:
	def __init__(self, logdata, start):
		# [ 1391742897.95 ]   POINTER NEW mouse 192.168.0.31:Sanghwa
		# [ 1391742898.22 ]   POINTER MOVE 192.168.0.31:Sanghwa 1352 560
		# [ 1391742898.55 ]   POINTER REMOVE mouse 192.168.0.31:Sanghwa
		# [ 1391742994.05 ]   POINTER CLICK 192.168.0.28:KSY 1318 768
		# [ 1391742994.18 ]   POINTER RELEASE 192.168.0.28:KSY 1318 768
		# [ 1391742994.05 ]   POINTER DCLICK 192.168.0.28:KSY 1318 768
		self.log_time = float(logdata[1])
		self.time = self.log_time - start
		type = logdata[4] 
		self.x = 0
		self.y = 0
		self.pop_x = 0
		self.pop_y = 0
		if type == "NEW" : 
			self.mode = LOG_POINTER_NEW 
		elif type == "MOVE" : 
			self.mode = LOG_POINTER_MOVE 
		elif type == "REMOVE" : 
			self.mode = LOG_POINTER_REMOVE 
		elif type == "CLICK" : 
			self.mode = LOG_POINTER_CLICK
			'''
			if logdata[7] == 'DOWN' :
				if logdata[6] == 'LEFT' :
					self.mode = LOG_POINTER_CLICK
				else :
					self.mode = LOG_POINTER_RCLICK
			else : 
				self.mode = LOG_POINTER_RELEASE
			'''
		elif type == "RELEASE" : 
			self.mode = LOG_POINTER_RELEASE
		elif type == "DCLICK" : 
			self.mode = LOG_POINTER_DCLICK
		elif type == "WHEEL" : 
			self.mode = LOG_POINTER_WHEEL
		elif type == "RCLICK" : 
			self.mode = LOG_POINTER_RCLICK
		elif type == "TWO_FINGERS" : 
			self.mode = LOG_POINTER_TWO_SWIPE
			# 6 , right, left, up, down
		elif type == "CONNECT_TWO" : 
			self.mode = LOG_POINTER_TWO_SWIPE
		elif type == "THREE_FINGERS" : 
			self.mode = LOG_POINTER_THREE_SWIPE
		elif type == "CONNECT_THREE" : 
			self.mode = LOG_POINTER_THREE_SWIPE
		elif type == "MAGNIFY" : 
			self.mode = LOG_POINTER_MAGNIFY
		elif type == "HIGHLIGHTT" :
                        self.mode = LOG_POINTER_HIGHLIGHTT
                elif type == "PCLICK" :
                        self.mode = LOG_POINTER_PCLICK
		else : 
			print logdata 
			self.mode = -1

		if self.mode == LOG_POINTER_MOVE or self.mode == LOG_POINTER_HIGHLIGHTT or self.mode == LOG_POINTER_PCLICK:
                        print "logdata...",self.mode,logdata[6],logdata[7]
			self.x = int(logdata[6])
			self.y = int(logdata[7])
		

# ------------------------------------------------------------
# Section LOG
# ------------------------------------------------------------
class SectionLogObj(LogObj):
	def __init__(self, name): 
		LogObj.__init__(self, name)

	def addSection(self, logdata, start):
		log = SectionLog(logdata, start)
		self.log_list.append(log)

	def analyze(self):
		noOfapply = 0
		for log in self.log_list :
			# hj
			#if log.mode == LOG_SECTION_DATAIN : 
			#if log.mode == LOG_SECTION_APPLY :
			#if log.mode == LOG_SECTION_NEW :
			#if log.mode == LOG_SECTION_CLEAR :
			#if log.mode == LOG_SECTION_SHRINK :
			#if log.mode == LOG_SECTION_DYNAMIC:
			if log.mode == LOG_SECTION_TILE:
				noOfapply += 1
		return noOfapply

class SectionLog:
	def __init__(self, logdata, start):
		# [ 1391742753.28 ]   SECTION NEW <ui.sections.Section instance at 0x257b368> 0 2156 748 2
		# [ 1391744909.44 ]   SECTION REMOVE <ui.sections.Section instance at 0x257b368>
		# NEW,  RESIZE, REMOVE, TILE, MINIMIZE_ALL

		self.log_time = float(logdata[1]) 
		self.time = self.log_time - start
		type = logdata[4] 
		if type == "NEW" : 
			self.mode = LOG_SECTION_NEW
			self.left = int(logdata[9])
			self.right = int(logdata[10])
			self.top = int(logdata[11])
			self.bottom = int(logdata[12])
                        self.direction = int(logdata[13])
			print self.left, self.right, self.bottom, self.top
		elif type == "REMOVE" : 
			self.mode = LOG_SECTION_REMOVE
		elif type == "RESIZE" : 
			self.mode = LOG_SECTION_RESIZE
			self.left = int(logdata[9])
			self.right = int(logdata[10])
			self.top = int(logdata[11])
			self.bottom = int(logdata[12])
			#print self.left, self.right, self.bottom, self.top
		elif type == "TILE" : 
			self.mode = LOG_SECTION_TILE
		elif type == "DYNAMIC" : 
			self.mode = LOG_SECTION_DYNAMIC
		elif type == "SHRINK" : 
			self.mode = LOG_SECTION_SHRINK
		elif type == "CLEAR" : 
			self.mode = LOG_SECTION_CLEAR
		elif type == "APPLY" : 
			self.mode = LOG_SECTION_APPLY
		elif type == "FREE" : 
			self.mode = LOG_SECTION_FREE
		elif type == "TILE_DISPLAY" : 
			self.mode = LOG_SECTION_TILE_DISPLAY
		elif type == "NORMAL" : 
			# unflocking....
			self.mode = LOG_SECTION_NORMAL
		elif type == "UNSET_DATA-IN" :
			self.mode = LOG_SECTION_NODATAIN
		elif type == "DATA-IN" :
			self.mode = LOG_SECTION_DATAIN
		else :
			print logdata
			self.mode = -1

# ------------------------------------------------------------
# Window LOG
# ------------------------------------------------------------
class WindowLogObj(LogObj):
	def __init__(self, name): 
		LogObj.__init__(self, name)
		self.lifetime = 0

		self.ave_size = 0
		self.max_size = 0
		self.min_size = 0

		self.no_maximize = 0
		self.no_minimize = 0
		self.no_restore = 0
		self.no_change = 0

	def addWindow(self, logdata, start):
		log = WindowLog(logdata, start)
		self.log_list.append(log)

	def analyze(self):
		start = 0
		average = 0
		max = 0
		min = 999 
		noOfaction = 0

		#print self.name, ": number of change =", str(len(self.log_list))

		last = 0
		for log in self.log_list: 
			# hj
			#if log.mode == LOG_WINDOW_MAXIMIZE_SCREEN :
			#if log.mode == LOG_WINDOW_MAXIMIZE:
			#if log.mode == LOG_WINDOW_SWAP:
			if log.mode == LOG_WINDOW_MOVE_TO:
				noOfaction += 1 
			elif  log.mode == LOG_WINDOW_NEW : 
				start = log.time 
				size_w = log.right - log.left
				size_h = log.top - log.bottom

				average = size_w * size_h 
				max = average
				min = average

			elif log.mode == LOG_WINDOW_CHANGE :
				size_w = log.right - log.left
				size_h = log.top - log.bottom

				area = size_w * size_h
				average = (average + area) / 2.0
				if area > max :
					max = area
				if area < min :
					min = area
				self.no_change += 1 
				#print self.name, log.time, log.left, log.right, log.top, log.bottom

			elif  log.mode == LOG_WINDOW_REMOVE : 
				self.lifetime = log.time - start
			elif log.mode == LOG_WINDOW_MAXIMIZE :
				self.no_maximize += 1
			elif log.mode == LOG_WINDOW_MINIMIZE :
				self.no_minimize += 1
			elif log.mode == LOG_WINDOW_RESTORE :
				self.no_restore += 1
			last = log.time 

		if self.lifetime == 0 : 
			self.lifetime = last - start

		return average, max, min, noOfaction

	def getLifetimes(self, start, end):
		lifetime= 0

		window_start = 0
		prev_start = -1 
		removed = False
		notCreated =True 
		for log in self.log_list: 
			if log.time > end : 
				if prev_start > 0 : 
					if removed == False : 
						lifetime =end - start
						prev_start = 0
						#print "1", self.name, window_start, end, lifetime, prev_start
				break
			notCreated = False 
			if log.time < start : 
				if log.mode == LOG_WINDOW_NEW or log.mode == LOG_WINDOW_CHANGE : 
					prev_start = log.time 
				elif log.mode == LOG_WINDOW_REMOVE :
					#prev_start = 0
					lifetime = 0
					removed = True
					break
				continue
			
			if prev_start > 0 : 
				window_start = start
				prev_start = -1

			if  log.mode == LOG_WINDOW_NEW : 
				window_start = log.time 
			elif log.mode == LOG_WINDOW_REMOVE :
				lifetime =log.time - window_start 
				removed = True

		if removed == False and notCreated == False :  
			if prev_start >= 0 : 
				window_start = start 
			lifetime =end - window_start 

		duration = 1.0 * (end - start)
		if duration > 0 : 
			lifetime= lifetime / duration
		else : 
			lifetime= 0.0
		return lifetime

	def getSizes(self, start, end):
		average = 0
		max = 0
		min = 999 

		last = 0
		for log in self.log_list: 
			if log.time > end : 
				break
			if log.time < start : 
				if  log.mode == LOG_WINDOW_NEW or log.mode == LOG_WINDOW_CHANGE : 
					size_w = log.right - log.left
					size_h = log.top - log.bottom
					average = size_w * size_h 
					max = average
					min = average
				elif log.mode == LOG_WINDOW_REMOVE :
					average = 0
					max = 0
					min = 0
				continue
			
			if  log.mode == LOG_WINDOW_NEW : 
				size_w = log.right - log.left
				size_h = log.top - log.bottom

				average = size_w * size_h 
				max = average
				min = average
			elif log.mode == LOG_WINDOW_CHANGE :
				size_w = log.right - log.left
				size_h = log.top - log.bottom

				area = size_w * size_h
				if average == 0 : 
					average = area
				else :	
					average = (average + area) / 2.0
				if area > max :
					max = area
				if area < min :
					min = area
				#print self.name, log.time, log.left, log.right, log.top, log.bottom

		display = 1.0 * DISPLAY_WIDTH * DISPLAY_HEIGHT
		average= average / display
		max = max / display
		min = min / display
		return average, max, min


class WindowLog:
	def __init__(self, logdata, start):
		# [ 1391744432.6 ]   WINDOW NEW imageviewer 0 100 700 100 369 1002 0 0 0 1 127.0.1.1:19010 600 269 0
		# [ 1391744432.76 ]   WINDOW Z 1 0 0
		# [ 1391744432.76 ]   WINDOW CHANGE imageviewer 0 100 700 99 368 1002 0 0 0 1 127.0.1.1:19010 600 269 1
		# [ 1391745039.28 ]   WINDOW MAXIMIZE 5 [166, 674, 372, 34]
		# [ 1393215348.97 ]   WINDOW REMOVE 23
		# appname, window id, left, right, bottom, top, sailid, zvalue, orientation, display id, app id, launcher id, resolution x, resolution y, my-message??? 
		# CHANGE, NEW, RENIOVE, MAXIMIZE, MINIMIZE, RESTORE, Z

		self.log_time = float(logdata[1]) 
		self.time = self.log_time - start
		type = logdata[4] 
		if type == "NEW" : 
			self.mode = LOG_WINDOW_NEW
		elif type == "CHANGE" : 
			self.mode = LOG_WINDOW_CHANGE
		elif type == "REMOVE" : 
			self.mode = LOG_WINDOW_REMOVE
		elif type == "MINIMIZE" : 
			self.mode = LOG_WINDOW_MINIMIZE
		elif type == "MAXIMIZE" : 
			self.mode = LOG_WINDOW_MAXIMIZE
		elif type == "RESTORE" : 
			self.mode = LOG_WINDOW_RESTORE
		elif type == "Z" : 
			self.mode = LOG_WINDOW_Z_CHANGE
		elif type == "MOVE_TO" :
			self.mode = LOG_WINDOW_MOVE_TO
		elif type == "SWAP" :
			self.mode = LOG_WINDOW_SWAP
		elif type == "MAXIMIZE_TO_SCREEN" :
			self.mode = LOG_WINDOW_MAXIMIZE_SCREEN
		else :
			# hyejung
			self.mode = -1

		if self.mode == LOG_WINDOW_NEW or self.mode == LOG_WINDOW_CHANGE :
			self.app_name = logdata[5]	
			self.left = int(logdata[7])
			self.right = int(logdata[8])
			self.bottom = int(logdata[9])	
			self.top = int(logdata[10])
			self.sail_id = int(logdata[11])
			self.zvalue = int(logdata[12])
			self.orientation = int(logdata[13])
			self.display_id = int(logdata[14])
			self.app_id = int(logdata[15])
			self.launcher_id = logdata[16]
			self.res_x = int(logdata[17]) 
			self.res_y = int(logdata[18]) 
